libvirt 虚拟机内存管理

·

libvirt windows虚拟机内存占用过高

虚拟机内存策略

  • QEMU 在虚拟机启动时,一次性分配固定的内存。 这部分内存被 预留并映射到宿主机进程(qemu-system-x86_64)。 从宿主机的角度看,这些内存都是“被占用的”。 即使 Windows 内部只使用很少,也不会被宿主机回收。
  • 💡 换句话说: 没有 balloon 驱动 = 没有动态回收机制。 QEMU 不知道 Windows 里面的内存使用情况,它只能把所有内存都“留给”虚拟机进程。
  • Windows 内存管理的特性加剧了现象 Windows 客户机即便空闲,也会: 启动缓存与系统文件预取; 启动 SuperFetch / SysMain; 各种服务预分配内存池; 内核会尽量“占用”空闲内存以提高 I/O 性能(File Cache)。 因此在任务管理器中看似“使用很多内存”,其实很多是 可释放缓存(Standby Memory)。 但宿主机(Linux + libvirt)看不到“哪些是可回收的”,于是整块都算“已用内存”。

Ballooning 如何解决这个问题?

Ballooning 的作用是 建立 Guest 与 Host 之间的内存使用反馈通道:

  • Guest 内 balloon 驱动 作为一个“伪设备”,可以向 Windows 内存管理器 申请分配内存(就像一个普通程序申请内存一样);

  • Windows 会从其空闲内存池中分配给 balloon 驱动;

  • 但 balloon 驱动 不会真正使用这些内存,只是“持有”它;

  • 由于这部分内存被 balloon 占用,QEMU 就知道:Guest 实际可用内存减少了,可以将对应物理页从宿主机释放;

  • 宿主机内存压力大时,libvirt 可通过 virsh setmem 命令 增大 balloon 大小,从而“回收”虚拟机内存。

  • Linux 虚拟机也一样:没有 balloon 驱动(如 virtio_balloon 模块未加载),同样会高占内存;

  • 现代替代方案:virtio-mem(动态内存插拔)比 balloon 更灵活,但 Windows 支持有限,balloon 仍是主流;

  • 内存共享(KSM)不能替代 balloon:KSM 只能合并完全相同的内存页(如多个 Win10 虚拟机的系统 DLL),对私有数据无效。

libvirt/QEMU 支持 Windows 虚拟机的内存 ballooning(动态内存管理)

需要在 宿主机与客户机两边都正确配置

  • windows 虚拟机上安装 virtio-win-xxx.iso 中的ballooning(其他的可以不安装,容易引起问题)
  • 配置虚拟机配置
<memballoon model='virtio'>
  <stats period='10'/>
</memballoon>